package com.xueqiu.movieplaymanagersystem.controller.admin;

import cn.hutool.crypto.asymmetric.RSA;
import com.wf.captcha.utils.CaptchaUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import com.xueqiu.movieplaymanagersystem.model.JsonResult;
import com.xueqiu.movieplaymanagersystem.entity.User;
import com.xueqiu.movieplaymanagersystem.service.UserService;
import com.xueqiu.movieplaymanagersystem.enums.CookieAge;
import com.xueqiu.movieplaymanagersystem.utils.KeyUtils;
import com.xueqiu.movieplaymanagersystem.utils.MD5Utils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.*;

/**
 * @author xueqiu
 */
@Controller
@RequestMapping("/admin")
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 登录，校验，记住密码，验证码，密码加密
     *
     * @param user          登陆数据源
     * @param bindingResult 校验工具
     * @param captcha       验证码
     * @param remember      记住我开关
     * @param response      响应
     * @param request       请求
     * @param publicKey     解密所需的盐
     * @return 登陆结果
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    @ResponseBody
    public JsonResult<String> login(
            @Validated
            User user,
            BindingResult bindingResult,
            @RequestParam(name = "captcha")
            String captcha,
            @RequestParam(name = "remember", required = false)
            Boolean remember,
            HttpServletResponse response,
            HttpServletRequest request,
            String publicKey
    ) {
        JsonResult<String> jsonResult = new JsonResult<>();
        //验证码
        if (!CaptchaUtil.ver(captcha, request)) {
            CaptchaUtil.clear(request);
            jsonResult.Error("验证码错误！");
            return jsonResult;
        }
        //数据源
        if (bindingResult.hasErrors()) {
            List<ObjectError> errors = bindingResult.getAllErrors();
            Set<String> errorMessages = new HashSet<>();
            for (ObjectError error : errors) {
                errorMessages.add(error.getDefaultMessage());
            }
            jsonResult.Error(Arrays.toString(errorMessages.toArray()));
            CaptchaUtil.clear(request);
            return jsonResult;
        }

        String password = KeyUtils.checkPassword(user.getPassword(), publicKey, redisTemplate);
        if (password == null) {
            jsonResult.Error("密码不存在!");
            CaptchaUtil.clear(request);
            return jsonResult;
        }
        if (password.length() < 6 || password.length() > 16) {
            jsonResult.Error("密码格式错误!");
            CaptchaUtil.clear(request);
            return jsonResult;
        }

        //密码加密
        String md5Password = MD5Utils.encode(password);
        //登录
        user.setPassword(md5Password);
        User login = userService.login(user);

        if (login == null) {
            jsonResult.Error("用户名或者密码错误！");
            CaptchaUtil.clear(request);
            return jsonResult;
        }

        jsonResult.Success("登陆成功！");
        CaptchaUtil.clear(request);
        //记住密码；生成cookie并设置生存周期
        if (remember != null && remember) {
            Cookie cookie01 = new Cookie("username", user.getUsername());
            cookie01.setMaxAge(CookieAge.WEEK.getCode());
            response.addCookie(cookie01);
            Cookie cookie02 = new Cookie("password", password);
            cookie02.setMaxAge(CookieAge.WEEK.getCode());
            response.addCookie(cookie02);
            Cookie cookie03 = new Cookie("remember", "true");
            cookie03.setMaxAge(CookieAge.WEEK.getCode());
            response.addCookie(cookie03);
        } else {
            //没有记住密码；则清除请求中的cookie，也就是无论是否存在cookie，都把cookie生存周期设置为0
            Cookie[] cookies = request.getCookies();
            for (Cookie cookie : cookies) {
                cookie.setMaxAge(CookieAge.ZERO.getCode());
                response.addCookie(cookie);
            }
        }
        //存入域中
        login.setPassword(password);
        request.getSession().setAttribute("user", login);
        return jsonResult;
    }

    /**
     * 退出登录
     *
     * @param session 域
     * @return 域中有`user`则删除后跳转；没有则直接跳转
     */
    @GetMapping("/logout")
    public String logout(HttpSession session) {
        Object user = session.getAttribute("user");
        if (user == null) {
            return "redirect:/admin/login.html";
        }
        session.removeAttribute("user");
        return "redirect:/admin/login.html";
    }

    /**
     * 获取公钥私钥对存入redis
     *
     * @return 返回公钥字符串
     */
    @GetMapping(value = "/getKey")
    @ResponseBody
    public JsonResult<String> getKeyOfRSA() {
        JsonResult<String> jsonResult = new JsonResult<>();
        RSA rsa = new RSA();
        String privateKeyBase64 = rsa.getPrivateKeyBase64();
        String publicKeyBase64 = rsa.getPublicKeyBase64();
        /*
         使用redis进行保存公钥私钥对
         boundValueOps(publicKeyBase64): 这个方法用于绑定一个特定的键（在这里是 publicKeyBase64），
         并返回一个可以操作该键的对象。这个对象专门用于对该键的值进行操作
         这里key = publicKeyBase64,value = privateKeyBase64
         */
        redisTemplate.boundValueOps(publicKeyBase64).set(privateKeyBase64);
        jsonResult.Success(publicKeyBase64);
        return jsonResult;
    }
}
